package com.xiaobai.common.utils.config.Tree;

import cn.hutool.core.collection.CollectionUtil;
import com.google.common.collect.Lists;
import com.xiaobai.common.utils.tool.CommonConstants;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@SuppressWarnings("all")
public class TreeHelper<K, T extends TreeNode<K, T>> {
    private List<T> datas;
    private K parentId;
    private K subId;

    public TreeHelper(List<T> datas, K parentId) {
        this.datas = datas;
        this.parentId = parentId;
    }

    public TreeHelper(List<T> datas, K parentId, K subId) {
        this.datas = datas;
        this.parentId = parentId;
        if (subId instanceof String && StringUtils.isBlank((String)subId)) {
            this.subId = null;
        } else {
            this.subId = subId;
        }

    }

    public List<T> create() {
        if (CollectionUtil.isEmpty(this.datas)) {
            return null;
        } else {
            List<T> trees = this.getNodeByParentId(this.parentId);
            if (Objects.nonNull(this.subId)) {
                trees = this.getSubTree(trees, this.subId);
            }

            return trees;
        }
    }

    public List<K> getChildrenIds() {
        if (CollectionUtil.isEmpty(this.datas)) {
            return null;
        } else {
            List<K> ids = new ArrayList();
            this.getNodeIdsByParentId(this.parentId, ids);
            return ids;
        }
    }

    private List<T> getNodeByParentId(K pid) {
        List<T> nodes = (List)this.datas.stream().filter((node) -> {
            if (Objects.isNull(pid)) {
                return node.getParentId() == null;
            } else {
                return pid.equals(node.getParentId());
            }
        }).collect(Collectors.toList());
        nodes.forEach((node) -> {
            List<T> subNodes = this.getNodeByParentId(node.getId());
            if (CollectionUtil.isNotEmpty(subNodes)) {
                node.setNodes(subNodes);
            }

        });
        return nodes;
    }

    private List<K> getNodeIdsByParentId(K pid, List<K> list) {
        List<T> nodes = (List)this.datas.stream().filter((node) -> {
            if (Objects.isNull(pid)) {
                return node.getParentId() == null;
            } else {
                return pid.equals(node.getParentId());
            }
        }).collect(Collectors.toList());
        nodes.forEach((node) -> {
            list.add(node.getId());
            this.getNodeIdsByParentId(node.getId(), list);
        });
        return list;
    }

    public List<T> getSubTree(List<T> trees, K subId) {
        if (subId != null && !subId.equals(CommonConstants.ROOT_ID)) {
            if (CollectionUtil.isNotEmpty(trees)) {
                List<T> subTree = Lists.newArrayList();
                Iterator var4 = trees.iterator();

                while(var4.hasNext()) {
                    T node = (T) var4.next();
                    if (node.getId().equals(subId)) {
                        subTree.add(node);
                        return subTree;
                    }

                    List<T> nextTrees = this.getSubTree(node.getNodes(), subId);
                    if (CollectionUtil.isNotEmpty(nextTrees)) {
                        return nextTrees;
                    }
                }
            }

            return null;
        } else {
            return trees;
        }
    }

    public List<T> getDatas() {
        return this.datas;
    }

    public K getParentId() {
        return this.parentId;
    }

    public K getSubId() {
        return this.subId;
    }

    public void setDatas(List<T> datas) {
        this.datas = datas;
    }

    public void setParentId(K parentId) {
        this.parentId = parentId;
    }

    public void setSubId(K subId) {
        this.subId = subId;
    }

    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof TreeHelper)) {
            return false;
        } else {
            TreeHelper<?, ?> other = (TreeHelper)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
                label47: {
                    Object this$datas = this.getDatas();
                    Object other$datas = other.getDatas();
                    if (this$datas == null) {
                        if (other$datas == null) {
                            break label47;
                        }
                    } else if (this$datas.equals(other$datas)) {
                        break label47;
                    }

                    return false;
                }

                Object this$parentId = this.getParentId();
                Object other$parentId = other.getParentId();
                if (this$parentId == null) {
                    if (other$parentId != null) {
                        return false;
                    }
                } else if (!this$parentId.equals(other$parentId)) {
                    return false;
                }

                Object this$subId = this.getSubId();
                Object other$subId = other.getSubId();
                if (this$subId == null) {
                    if (other$subId != null) {
                        return false;
                    }
                } else if (!this$subId.equals(other$subId)) {
                    return false;
                }

                return true;
            }
        }
    }

    protected boolean canEqual(Object other) {
        return other instanceof TreeHelper;
    }


    public String toString() {
        return "TreeHelper(datas=" + this.getDatas() + ", parentId=" + this.getParentId() + ", subId=" + this.getSubId() + ")";
    }

    public TreeHelper() {
    }
}

